home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / emac16as.arc / MINTFORM.ASM < prev    next >
Assembly Source File  |  1990-04-01  |  12KB  |  466 lines

  1. ;History:401,1
  2. ;Tue Sep 12 23:49:09 1989 Add the find_string entry point.
  3. ;10-01-88 14:45:52 make get_mint_space return four numbers.
  4. ;12-06-87 00:51:14 finish adding 256K of mint space.
  5. ;12-06-87 00:26:46 start adding support for 256K of mint space.
  6. ;11-16-87 23:18:00 call new_buffer from init_forms.
  7.     page    ,132
  8.  
  9.     .xlist
  10.     include    mintform.def
  11.     include    mint.def
  12.     .list
  13.  
  14. comment /
  15.  
  16. The forms:
  17.  
  18.     Forms are laid out as a linear list of forms.  formStore points to the
  19. beginning, and [topbot] points to the end.  The most recently defined forms are
  20. placed at the beginning of the list.  The forms consists of three elements: a
  21. header, the name, and the data.  The header contains the link to the next
  22. form, the length of the name, the length of the data, and the form pointer
  23. (which is always <= the length of the data).  The form structure is defined in
  24. the file 'mintform.def'.
  25.     When a form is to be looked up in form storage, the form is first
  26. hashed.  Then the form is looked up in the list of hash links.  A linear search
  27. is performed for all the forms that hash to that value.
  28.  
  29.     formhash is the hashing table for form names.  It is a list of
  30. pointers to forms.  Each form, in turn, has a pointer to the next form
  31. whose name hashes to the same entry in formhash. To add a new form, we
  32. must add the name to the proper place in the table.  To delete a form, the
  33. form name must be removed from formhash.  Their links in formhash and each
  34. of the forms must be updated, then the remaining forms get moved up in
  35. memory.
  36.  
  37.     Also, whenever a form gets looked up, it is placed at the head of
  38. the chain of hash pointers.  The assumption is that it will be looked up
  39. again shortly.
  40.  
  41. /
  42.  
  43.  
  44. formSeg    segment    byte public
  45.  
  46.     define_buffer    form_
  47.  
  48.     public    syntax_table
  49. syntax_table    dw    NIL
  50. ;don't put anything here.
  51. formhashsize    equ    256
  52. formhash    dw formhashsize dup(NIL)
  53.  
  54. formStore    label    byte
  55.  
  56.  
  57. formSeg    ends
  58.  
  59.  
  60. segmoffs    struc
  61. offs        dw    ?
  62. segm        dw    ?
  63. segmoffs    ends
  64.  
  65.  
  66. data    segment byte public
  67.  
  68.     public    syntax_seg
  69. syntax_seg    dw    formSeg        ;segment holding syntax table.
  70.  
  71. this_segment    dw    ?        ;points to next formSegments to get.
  72. this_form    dd    ?        ;current form while enumerating.
  73.  
  74.     public    formSeg0, formSeg1, formSeg2, formSeg3
  75. formSegments    label    word
  76. formSeg0    dw    ?
  77. formSeg1    dw    ?
  78. formSeg2    dw    ?
  79. formSeg3    dw    ?
  80.  
  81.     extrn    data_bottop: word
  82.  
  83. data    ends
  84.  
  85.  
  86. code    segment byte public
  87.  
  88.     assume cs:code
  89.  
  90.     extrn    buffer_free: near
  91.     extrn    new_buffer: near
  92.     extrn    put_number: near
  93.  
  94.     public    init_forms
  95. init_forms:
  96.     mov    cx,4
  97.     mov    bx,offset formSegments
  98. init_forms_0:
  99.     assume    ds:data, es:data
  100.     push    bx
  101.     push    cx
  102.     mov    cx,offset formStore
  103.     call    new_buffer
  104.     pop    cx
  105.     pop    bx
  106.     jc    init_forms_1
  107.     xchgdses
  108.     assume    ds:data, es:formSeg
  109.     mov    [bx],es                ;remember this form segment.
  110.     add    bx,2
  111.     push    cx
  112.     mov    di,offset syntax_table        ;null out the hash table.
  113.     xor    ax,ax
  114.     mov    cx,256 + 1
  115.     rep    stosw
  116.     mov    ax,offset formStore        ;->end of forms.
  117.     mov    form_topbot,ax
  118.     mov    form_bottop,ax
  119.     mov    form_botbot,ax
  120.     esdata
  121.     pop    cx
  122.     loop    init_forms_0
  123.     clc
  124. init_forms_1:
  125.     ret
  126.  
  127.  
  128.     public    get_mint_space
  129. get_mint_space:
  130. ;enter with di -> place to put numbers.
  131. ;return four numbers giving the bytes of mint space available,
  132. ;  di ->end of strings.
  133.     mov    dx,ds            ;start with ds.
  134.     mov    cx,4            ;do four segments.
  135. get_mint_space_1:
  136.     push    ds            ;get the next segment
  137.     mov    ds,dx
  138.     assume    ds:formseg
  139.     mov    dx,form_next_buffer
  140.     mov    ds,dx
  141.     mov    ax,form_bottop        ;get the free space for this buffer.
  142.     sub    ax,form_topbot
  143.     pop    ds
  144.     assume    ds:data
  145.  
  146.     push    dx
  147.     push    cx
  148.     mov    cx,0            ;use only as many digits as is needed.
  149.     mov    bx,10
  150.     call    put_number
  151.     mov    al,','            ;seperate them by commas.
  152.     stosb
  153.     pop    cx
  154.     pop    dx
  155.     loop    get_mint_space_1
  156.     ret
  157.  
  158.  
  159. ;first_form sets us up to enumerate the forms (in no particular order).
  160. ;  Returns es:bx ->next form, zr if there is no next form.  Do not assume
  161. ;  that es will remain the same from one call to the next.
  162.     public    first_form, next_form
  163. first_form:
  164.     assume    ds:data, es:data
  165.     mov    this_segment,offset formSegments
  166. next_segment:
  167.     assume    ds:data, es:nothing
  168.     mov    bx,this_segment
  169.     add    this_segment,2            ;postincrement to the next seg.
  170.     cmp    bx,offset formSegments + 4*2    ;last form segment?
  171.     jz    next_last            ;yes - we're done.
  172.     mov    ax,[bx]                ;get the formSegment.
  173.     mov    this_form.segm,ax
  174.     mov    this_form.offs,offset formStore    ;->beginning of forms.
  175. next_form:
  176.     les    bx,this_form
  177.     assume    es:formSeg
  178.     mov    ax,formSeg:[bx].form_length    ;postincrement to the next form.
  179.     add    this_form.offs,ax
  180.     cmp    bx,form_topbot            ;go if we have no more forms.
  181.     je    next_segment
  182. next_last:
  183.     ret
  184.  
  185.  
  186. ;enter with ds:bx -> a form.  Make that form be the syntax table.
  187.  
  188.     public    store_syntax_table
  189. store_syntax_table:
  190.     assume    ds:formSeg, es:data
  191.     mov    syntax_table,bx
  192.     mov    syntax_seg,ds
  193.     ret
  194.  
  195.  
  196. ;define a form.  Enter with:
  197. ;    si => name
  198. ;    cx = name length
  199. ;    di => data
  200. ;    dx = data length
  201. ;    bx = form pointer.
  202.  
  203.     public    define_form
  204. define_form:
  205.     assume    ds:data, es:data
  206.     push    bx            ;save the form pointer.
  207.     call    find_form        ;see if it already exists.
  208.     jc    define_form_1        ;it doesn't.
  209.     assume    es:formSeg
  210. ;check to see if the form is already big enough.
  211.     cmp    dx,formSeg:[bx].data_length
  212.     ja    define_form_3            ;it isn't.
  213.     pop    formSeg:[bx].form_pointer        ;set the form pointer.
  214.     mov    si,di                ;prepare to move the data.
  215.     lea    di,formSeg:[bx].name_offset    ;->name.
  216.     add    di,cx                ;->data.
  217.     mov    formSeg:[bx].data_length,dx    ;set the data length.
  218.     mov    cx,dx                ;copy the new data in.
  219.     rep    movsb
  220.     esdata
  221.     ret
  222. define_form_3:
  223.     assume    es:formSeg
  224.     push    di            ;delete the form pointed to by es:bx
  225.     push    si
  226.     push    cx
  227.     call    delete_form
  228.     pop    cx
  229.     pop    si
  230.     pop    di
  231.     esdata
  232. define_form_1:
  233.     pop    bx        ;restore form pointer.
  234.     push    di
  235.     push    bx
  236.     push    si
  237.     push    cx
  238.     call    hash_func        ;exit with es:[bx]->hash entry.
  239.     assume    es:formSeg
  240.     add    cx,(size form_struc)    ;compute amount of space needed.
  241.     add    cx,dx
  242.     push    cx            ;push the size
  243.     mov    ax,es
  244.     call    buffer_free
  245.     jc    define_form_2            ;go if we can't get enough mem.
  246.     mov    di,form_topbot
  247.     pop    formSeg:[di].form_length        ;get the total size. (pushed as cx)
  248.     pop    cx                ;we have to pop into cx, because we
  249.     mov    formSeg:[di].name_length,cx    ;  need it later for the movsb.
  250.     mov    formSeg:[di].data_length,dx
  251.     pop    si                ;restore ->name
  252.     pop    formSeg:[di].form_pointer
  253.     mov    ax,formSeg:[bx]            ;get current formhash
  254.     mov    formSeg:[bx],di            ;make formhash point to us.
  255.     mov    formSeg:[di].hash_link,ax        ;make us point to current formhash.
  256.     add    di,name_offset            ;lea    di,[di].name_offset
  257.     rep    movsb
  258.     pop    si                ;restore ->data
  259.     mov    cx,dx
  260.     rep    movsb
  261.     mov    form_topbot,di            ;remember the new end.
  262.     esdata
  263.     ret
  264. define_form_2:
  265.     call    nomem
  266.  
  267.  
  268. ;Find a form.  Enter with:
  269. ;    si -> name
  270. ;    cx = name length
  271. ;Preserve di
  272. ;Exit with:
  273. ;    nc if form found, es:bx -> form
  274. ;    cy if form not found, es=data
  275.     public    find_form
  276. find_form:
  277.     assume    ds:data, es:data
  278.     push    dx
  279.     push    di
  280.     call    hash_func
  281.     assume    es:formSeg
  282.     push    bx            ;remember the formhash pointer.
  283.     xor    dx,dx
  284.     mov    bx,formSeg:[bx]        ;get ->first form that hashes here.
  285. find_form_1:
  286.     cmp    bx,NIL                ;end of list?
  287.     je    find_form_2            ;yes, we didn't find it.
  288.     cmp    cx,formSeg:[bx].name_length    ;lengths equal?
  289.     jne    find_form_3            ;no, go to next.
  290.     lea    di,formSeg:[bx].name_offset    ;compare names.
  291.     push    si
  292.     push    cx
  293.     rep    cmpsb
  294.     pop    cx
  295.     pop    si
  296.     jne    find_form_3        ;names not equal.
  297.     pop    di            ;restore the formhash pointer.
  298.     or    dx,dx            ;did we find it first?
  299.     je    find_form_4        ;yes - that's where we want it.
  300.     mov    ax,formSeg:[di]
  301.     mov    formSeg:[di],bx        ;make head -> found.
  302.     xchg    ax,formSeg:[bx].hash_link    ;make found -> old head.
  303.     mov    di,dx
  304.     mov    formSeg:[di].hash_link,ax    ;make pred(found) -> succ(found).
  305. find_form_4:
  306.     clc                ;found the form!
  307.     pop    di
  308.     pop    dx
  309.     ret
  310. find_form_3:
  311.     assume    es:formSeg
  312.     mov    dx,bx
  313.     mov    bx,formSeg:[bx].hash_link
  314.     jmp    find_form_1
  315. find_form_2:
  316.     pop    bx        ;restore the formhash pointer.
  317.     esdata
  318.     stc            ;didn't find the form!
  319.     pop    di
  320.     pop    dx
  321.     ret
  322.  
  323.  
  324. ;delete a form.  Enter with:
  325. ;    es:bx=>form
  326.  
  327.     public    delete_form
  328. delete_form:
  329. ;delete the form from the hashing table.
  330.     assume    ds:data, es:formSeg
  331.     mov    di,bx            ;make a copy of the pointer to the form.
  332.     mov    cx,formSeg:[bx].name_length
  333.     lea    si,formSeg:[bx].name_offset
  334.     xchgdses
  335.     assume    ds:formSeg, es:data
  336.     call    hash_func
  337.     assume    es:formSeg
  338.     sub    bx,hash_link        ;pretend that formhash is a form itself.
  339. delete_form_1:
  340.     cmp    formSeg:[bx].hash_link,di    ;does this form point to us?
  341.     je    delete_form_2        ;yes.
  342.     mov    bx,formSeg:[bx].hash_link    ;no - go to the next form.
  343.     jmp    delete_form_1
  344. delete_form_2:
  345.     mov    ax,formSeg:[di].hash_link    ;unlink us from the list.
  346.     mov    formSeg:[bx].hash_link,ax
  347. ;check for deletion of the syntax table.
  348.     cmp    di,syntax_table
  349.     jne    delete_form_7
  350.     mov    syntax_table,NIL    ;if we're deleting it, put NIL in.
  351. delete_form_7:
  352. ;now adjust the hash links in formhash.
  353.     mov    ax,formSeg:[di].form_length
  354.     mov    bx,offset syntax_table
  355.     mov    cx,formhashsize+1    ;add one for the syntax table.
  356. delete_form_3:
  357.     cmp    formSeg:[bx],di        ;do we need to adjust this one?
  358.     jbe    delete_form_4        ;no.
  359.     sub    formSeg:[bx],ax        ;yes - do it.
  360. delete_form_4:
  361.     add    bx,2
  362.     loop    delete_form_3
  363. ;now adjust all the hash links in the forms.  Notice that we are adjusting
  364. ;  the hash link in the form we are about to delete, but it doesn't hurt.
  365. ;  We can also presume the existence of at least one form at this point.
  366.     mov    bx,offset formStore        ;->beginning of forms.
  367. delete_form_5:
  368.     cmp    formSeg:[bx].hash_link,di    ;do we need to adjust this one?
  369.     jbe    delete_form_6        ;no.
  370.     sub    formSeg:[bx].hash_link,ax    ;yes - do it.
  371. delete_form_6:
  372.     add    bx,formSeg:[bx].form_length    ;compute the form after this one.
  373.     cmp    bx,form_topbot            ;no forms after this one.
  374.     jb    delete_form_5
  375.     mov    si,di            ;now move every form after this one down.
  376.     add    si,ax
  377.     mov    cx,form_topbot
  378.     sub    cx,si
  379.     rep    movsb
  380.     mov    form_topbot,di        ;remember the new form_topbot.
  381.     dsdata
  382.     esdata
  383.     ret
  384.  
  385.  
  386. ;find the form whose name is given in arg1.  Return the form pointer in
  387. ;ds:si, and the number of bytes remaining in the form in cx.
  388.     public    find_arg1
  389. find_arg1:
  390.     mov    cx,1
  391. ;fall through to find_arg
  392.  
  393. ;find the form whose name is given in the argument specified in cx.  Return
  394. ;  the form pointer in ds:si, and the number of bytes remaining in the form in
  395. ;  cx, and the pointer to the form in bx.
  396.     public    find_arg
  397. find_arg:
  398.     assume    ds:data, es:data
  399.     call    getarg
  400.     public    find_string
  401. find_string:
  402.     call    find_form
  403.     jc    find_arg1_1            ;if form doesn't exist, exit.
  404.     xchgdses
  405.     assume    ds:formSeg, es:data
  406.     lea    si,formSeg:[bx].name_offset    ;make si => form.data
  407.     add    si,formSeg:[bx].name_length
  408.     add    si,formSeg:[bx].form_pointer
  409.     mov    cx,formSeg:[bx].data_length    ;make cx = number of bytes left.
  410.     sub    cx,formSeg:[bx].form_pointer
  411.     clc                    ;remember that form was found.
  412. find_arg1_1:
  413.     ret
  414.  
  415.  
  416. hash_func:
  417. ;enter with si,cx ->name to be hashed.
  418. ;exit with entry into hash table in ds:bx
  419. ;preserve dl.
  420.     assume    ds:nothing
  421.     push    si
  422.     push    cx
  423.     xor    bx,bx            ;start with zero.
  424.     jcxz    hash_func_1
  425.     xor    ah,ah
  426. hash_func_2:
  427.     lodsb
  428.     add    bx,ax
  429.     loop    hash_func_2
  430. hash_func_1:
  431.     mov    al,bl            ;save the low byte
  432.     mov    bl,bh
  433.     mov    bh,0
  434.     and    bl,3            ;four segments = two bits.
  435.     add    bx,bx            ;we're accessing words.
  436.     mov    es,formSegments[bx]    ;get the correct segment.
  437.     mov    bl,al            ;get the low byte back.  No need to
  438.                     ;zero bh again.
  439.     add    bx,bx
  440.     add    bx,offset formhash
  441.     pop    cx
  442.     pop    si
  443.     ret
  444.  
  445.  
  446. ;Adjust the form pointer after building a value which affects the
  447. ;  form pointer.  The new form pointer is derived from the count
  448. ;  of characters left in cx.  The form is pointed to by bx.
  449.     public    return_form
  450. return_form:
  451.     assume    ds:formSeg, es:data
  452.     mov    ax,formSeg:[bx].data_length
  453.     sub    ax,cx
  454.     mov    formSeg:[bx].form_pointer,ax
  455.     dsdata
  456.     jmp    return_tos
  457.  
  458.  
  459.     extrn    return_tos: near
  460.     extrn    getarg: near
  461.     extrn    nomem: near
  462. code    ends
  463.  
  464.     end
  465.  
  466.